;;; examples-of-lexical-addressing-and-tail-call-annotation.scm
;;; Examples of what my compiler outputs for the tail-call annotation
;;; and lexical addressing problems. Note that my compiler generates
;;; slightly different tags for the AST than what the class was asked
;;; to generate. This should not be a problem.
;;;
;;; Programmer: Mayer Goldberg, 2009

(load "H:/hw4/q2/q2.scm")           ;;; pe->lex-pe
(load "H:/hw4/q1/q1.scm")           ;;; annotate-tail-calls
(load "H:/hw3/q12/compiler.scm")    ;;; parse, box-set

(define (rep e)
  (pe->lex-pe (annotate-tail-calls (box-set (parse e)))))

(and
 
(equal? (rep '(lambda (x) (x x)))
        '(lambda-simple (x) (tc-applic (param-var x 0) ((param-var x 0)))))

(equal? (rep '((lambda (x) (x x)) (lambda (x) (x x))))
             '(tc-applic
               (lambda-simple (x) (tc-applic (param-var x 0) ((param-var x 0))))
               ((lambda-simple (x) (tc-applic (param-var x 0) ((param-var x 0)))))))

(equal? (rep '(lambda (x) (x (x x))))
             '(lambda-simple
               (x)
               (tc-applic (param-var x 0) ((applic (param-var x 0) ((param-var x 0)))))))

(equal? (rep '(define fact
                (lambda (n)
                  (if (zero? n) 
                      1
                      (* n (fact (- n 1)))))))
        '(define (free-var fact)
           (lambda-simple
            (n)
            (if-3 (applic (free-var zero?) ((param-var n 0)))
                  (const 1)
                  (tc-applic
                   (free-var *)
                   ((param-var n 0)
                    (applic
                     (free-var fact)
                     ((applic (free-var -) ((param-var n 0) (const 1)))))))))))

(equal? (rep '(define y
                (lambda (f)
                  ((lambda (x)
                     (f (lambda args
                          (apply (x x) args))))
                   (lambda (x)
                     (f (lambda args
                          (apply (x x) args))))))))
        '(define (free-var y)
          (lambda-simple
           (f)
           (tc-applic
            (lambda-simple
             (x)
             (tc-applic
              (bound-var f 0 0)
              ((lambda-variadic
                args
                (tc-applic
                 (free-var apply)
                 ((applic (bound-var x 0 0) ((bound-var x 0 0))) (param-var args 0)))))))
            ((lambda-simple
              (x)
              (tc-applic
               (bound-var f 0 0)
               ((lambda-variadic
                 args
                 (tc-applic
                  (free-var apply)
                  ((applic (bound-var x 0 0) ((bound-var x 0 0)))
                   (param-var args 0))))))))))))
        
        
(equal? (rep '(lambda (a) 
                (lambda (b)
                  (lambda (c)
                    ((a c) (b c))))))
        '(lambda-simple
          (a)
          (lambda-simple
           (b)
           (lambda-simple
            (c)
            (tc-applic
             (applic (bound-var a 1 0) ((param-var c 0)))
             ((applic (bound-var b 0 0) ((param-var c 0)))))))))


(equal? (rep '(define order
               (lambda (<)
                 (letrec ((loop
                           (lambda (a s)
                             (or (null? s)
                                 (and (< a (car s))
                                      (loop (car s) (cdr s)))))))
                   (lambda (a . s)
                     (loop a s))))))
             '(define (free-var order)
               (lambda-simple
                (<)
                (tc-applic
                 (lambda-simple
                  (loop)
                  (seq ((set (param-var loop 0)
                             (applic (free-var cons) ((param-var loop 0) (const ()))))
                        (applic
                         (free-var set-car!)
                         ((param-var loop 0)
                          (lambda-simple
                           (a s)
                           (or ((applic (free-var null?) ((param-var s 1)))
                                (if-3 (applic
                                       (bound-var < 1 0)
                                       ((param-var a 0)
                                        (applic (free-var car) ((param-var s 1)))))
                                      (tc-applic
                                       (applic (free-var car) ((bound-var loop 0 0)))
                                       ((applic (free-var car) ((param-var s 1)))
                                        (applic (free-var cdr) ((param-var s 1)))))
                                      (const #f)))))))
                        (lambda-opt
                         (a)
                         s
                         (tc-applic
                          (applic (free-var car) ((bound-var loop 0 0)))
                          ((param-var a 0) (param-var s 1)))))))
                 ((const #f))))))





;(equal? (rep (define map
;     (letrec ((map-list
;	       (lambda (f lists)
;		 (if (null? (car lists)) '()
;		     (cons (apply f (map-one car lists))
;			   (map-list f (map-one cdr lists))))))
;	      (map-one
;	       (lambda (f s)
;		 (if (null? s) '()
;		     (cons (f (car s))
;			   (map-one f (cdr s)))))))
;       (lambda (f . args)
;	 (map-list f args))))
;(define (free-var map)
;     (applic
;      (lambda-simple
;       (map-list map-one)
;       (seq ((set (param-var map-list 0)
;		  (applic (free-var cons) ((param-var map-list 0) (const ()))))
;	     (set (param-var map-one 1)
;		  (applic (free-var cons) ((param-var map-one 1) (const ()))))
;	     (applic
;	      (free-var set-car!)
;	      ((param-var map-list 0)
;	       (lambda-simple
;		(f lists)
;		(if-3 (applic
;		      (free-var null?)
;		      ((applic (free-var car) ((param-var lists 1)))))
;		     (const ())
;		     (tc-applic
;		      (free-var cons)
;		      ((applic
;			(free-var apply)
;			((param-var f 0)
;			 (applic
;			  (applic
;			   (free-var car)
;			   ((bound-var map-one 0 1)))
;			  ((free-var car) (param-var lists 1)))))
;		       (applic
;			(applic (free-var car) ((bound-var map-list 0 0)))
;			((param-var f 0)
;			 (applic
;			  (applic
;			   (free-var car)
;			   ((bound-var map-one 0 1)))
;			  ((free-var cdr) (param-var lists 1)))))))))))
;	     (applic
;	      (free-var set-car!)
;	      ((param-var map-one 1)
;	       (lambda-simple
;		(f s)
;		(if-3 (applic (free-var null?) ((param-var s 1)))
;		     (const ())
;		     (tc-applic
;		      (free-var cons)
;		      ((applic
;			(param-var f 0)
;			((applic (free-var car) ((param-var s 1)))))
;		       (applic
;			(applic (free-var car) ((bound-var map-one 0 1)))
;			((param-var f 0)
;			 (applic (free-var cdr) ((param-var s 1)))))))))))
;	     (lambda-opt
;	      (f)
;	      args
;	      (tc-applic
;	       (applic (free-var car) ((bound-var map-list 0 0)))
;	       ((param-var f 0) (param-var args 1)))))))
;      ((const #f) (const #f))))
;(equal? (rep (define member?
;     (lambda (a s)
;       (ormap (lambda (b) (eq? a b)) s)))
;(define (free-var member?)
;     (lambda-simple
;      (a s)
;      (tc-applic
;       (free-var ormap)
;       ((lambda-simple
;	 (b)
;	 (tc-applic (free-var eq?) ((bound-var a 0 0) (param-var b 0))))
;	(param-var s 1)))))
;(equal? (rep (define andmap
;     (lambda (f . s)
;       (letrec ((loop
;		 (lambda (s)
;		   (or (null? (car s))
;		       (and (apply f (map car s))
;			    (loop (map cdr s)))))))
;	 (loop s))))
;(define (free-var andmap)
;     (lambda-opt
;      (f)
;      s
;      (tc-applic
;       (lambda-simple
;	(loop)
;	(seq ((set (param-var loop 0)
;		   (applic (free-var cons) ((param-var loop 0) (const ()))))
;	      (applic
;	       (free-var set-car!)
;	       ((param-var loop 0)
;		(lambda-simple
;		 (s)
;		 (or ((applic
;		       (free-var null?)
;		       ((applic (free-var car) ((param-var s 0)))))
;		      (if-3 (applic
;			    (free-var apply)
;			    ((bound-var f 1 0)
;			     (applic
;			      (free-var map)
;			      ((free-var car) (param-var s 0)))))
;			   (tc-applic
;			    (applic (free-var car) ((bound-var loop 0 0)))
;			    ((applic
;			      (free-var map)
;			      ((free-var cdr) (param-var s 0)))))
;			   (const #f)))))))
;	      (tc-applic
;	       (applic (free-var car) ((param-var loop 0)))
;	       ((bound-var s 0 1))))))
;       ((const #f)))))
;(equal? (rep (define string->list
;     (letrec ((loop
;	       (lambda (str n s)
;		 (if (= n -1) s
;		     (loop str
;			   (- n 1)
;			   (cons (string-ref str n) s))))))
;       (lambda (str)
;	 (loop str (- (string-length str) 1) '()))))
;(define (free-var string->list)
;     (applic
;      (lambda-simple
;       (loop)
;       (seq ((set (param-var loop 0)
;		  (applic (free-var cons) ((param-var loop 0) (const ()))))
;	     (applic
;	      (free-var set-car!)
;	      ((param-var loop 0)
;	       (lambda-simple
;		(str n s)
;		(if-3 (applic (free-var =) ((param-var n 1) (const -1)))
;		     (param-var s 2)
;		     (tc-applic
;		      (applic (free-var car) ((bound-var loop 0 0)))
;		      ((param-var str 0)
;		       (applic (free-var -) ((param-var n 1) (const 1)))
;		       (applic
;			(free-var cons)
;			((applic
;			  (free-var string-ref)
;			  ((param-var str 0) (param-var n 1)))
;			 (param-var s 2)))))))))
;	     (lambda-simple
;	      (str)
;	      (tc-applic
;	       (applic (free-var car) ((bound-var loop 0 0)))
;	       ((param-var str 0)
;		(applic
;		 (free-var -)
;		 ((applic (free-var string-length) ((param-var str 0)))
;		  (const 1)))
;		(const ())))))))
;      ((const #f))))
;(equal? (rep (define is-equal?
;     (let ((void-object (if #f #f)))
;       (letrec ((equal?
;		 (lambda (a b)
;		   (cond
;		    ;; bool
;		    ((and (boolean? a) (boolean? b))
;		     (if a b (not b)))
;		    ;; char
;		    ((and (char? a) (char? b)) (char=? a b))
;		    ;; nil
;		    ((null? a) (null? b))
;		    ;; number
;		    ((and (number? a) (number? b)) (= a b))
;		    ;; pair
;		    ((and (pair? a) (pair? b))
;		     (and (equal? (car a) (car b))
;			  (equal? (cdr a) (cdr b))))
;		    ;; string
;		    ((and (string? a) (string? b)) (string=? a b))
;		    ;; symbol
;		    ((and (symbol? a) (symbol? b)) (eq? a b))
;		    ;; vector
;		    ((and (vector? a) (vector? b)
;			  (= (vector-length a) (vector-length b)))
;		     (map equal? (vector->list a) (vector->list b)))
;		    ;; void
;		    ((eq? a void-object) (eq? b void-object))
;		    (else #f)))))
;	 equal?)))
;(define (free-var is-equal?)
;     (applic
;      (lambda-simple
;       (void-object)
;       (tc-applic
;	(lambda-simple
;	 (equal?)
;	 (seq ((set (param-var equal? 0)
;		    (applic (free-var cons) ((param-var equal? 0) (const ()))))
;	       (applic
;		(free-var set-car!)
;		((param-var equal? 0)
;		 (lambda-simple
;		  (a b)
;		  (if-3 (if-3 (applic (free-var boolean?) ((param-var a 0)))
;			    (applic (free-var boolean?) ((param-var b 1)))
;			    (const #f))
;		       (if-3 (param-var a 0)
;			    (param-var b 1)
;			    (tc-applic (free-var not) ((param-var b 1))))
;		       (if-3 (if-3 (applic (free-var char?) ((param-var a 0)))
;				 (applic (free-var char?) ((param-var b 1)))
;				 (const #f))
;			    (tc-applic
;			     (free-var char=?)
;			     ((param-var a 0) (param-var b 1)))
;			    (if-3 (applic (free-var null?) ((param-var a 0)))
;				 (tc-applic
;				  (free-var null?)
;				  ((param-var b 1)))
;				 (if-3 (if-3 (applic
;					    (free-var number?)
;					    ((param-var a 0)))
;					   (applic
;					    (free-var number?)
;					    ((param-var b 1)))
;					   (const #f))
;				      (tc-applic
;				       (free-var =)
;				       ((param-var a 0) (param-var b 1)))
;				      (if-3 (if-3 (applic
;						 (free-var pair?)
;						 ((param-var a 0)))
;						(applic
;						 (free-var pair?)
;						 ((param-var b 1)))
;						(const #f))
;					   (if-3 (applic
;						 (applic
;						  (free-var car)
;						  ((bound-var
;						    equal?
;						    0
;						    0)))
;						 ((applic
;						   (free-var car)
;						   ((param-var a 0)))
;						  (applic
;						   (free-var car)
;						   ((param-var
;						     b
;						     1)))))
;						(tc-applic
;						 (applic
;						  (free-var car)
;						  ((bound-var
;						    equal?
;						    0
;						    0)))
;						 ((applic
;						   (free-var cdr)
;						   ((param-var a 0)))
;						  (applic
;						   (free-var cdr)
;						   ((param-var
;						     b
;						     1)))))
;						(const #f))
;					   (if-3 (if-3 (applic
;						      (free-var
;						       string?)
;						      ((param-var
;							a
;							0)))
;						     (applic
;						      (free-var
;						       string?)
;						      ((param-var
;							b
;							1)))
;						     (const #f))
;						(tc-applic
;						 (free-var string=?)
;						 ((param-var a 0)
;						  (param-var b 1)))
;						(if-3 (if-3 (applic
;							   (free-var
;							    symbol?)
;							   ((param-var
;							     a
;							     0)))
;							  (applic
;							   (free-var
;							    symbol?)
;							   ((param-var
;							     b
;							     1)))
;							  (const
;							   #f))
;						     (tc-applic
;						      (free-var eq?)
;						      ((param-var a 0)
;						       (param-var
;							b
;							1)))
;						     (if-3 (if-3 (applic
;								(free-var
;								 vector?)
;								((param-var
;								  a
;								  0)))
;							       (if-3 (applic
;								     (free-var
;								      vector?)
;								     ((param-var
;								       b
;								       1)))
;								    (applic
;								     (free-var
;								      =)
;								     ((applic
;								       (free-var
;									vector-length)
;								       ((param-var
;									 a
;									 0)))
;								      (applic
;								       (free-var
;									vector-length)
;								       ((param-var
;									 b
;									 1)))))
;								    (const
;								     #f))
;							       (const
;								#f))
;							  (tc-applic
;							   (free-var
;							    map)
;							   ((applic
;							     (free-var
;							      car)
;							     ((bound-var
;							       equal?
;							       0
;							       0)))
;							    (applic
;							     (free-var
;							      vector->list)
;							     ((param-var
;							       a
;							       0)))
;							    (applic
;							     (free-var
;							      vector->list)
;							     ((param-var
;							       b
;							       1)))))
;							  (if-3 (applic
;								(free-var
;								 eq?)
;								((param-var
;								  a
;								  0)
;								 (bound-var
;								  void-object
;								  1
;								  0)))
;							       (tc-applic
;								(free-var
;								 eq?)
;								((param-var
;								  b
;								  1)
;								 (bound-var
;								  void-object
;								  1
;								  0)))
;							       (const
;								#f)))))))))))))
;	       (tc-applic (free-var car) ((param-var equal? 0))))))
;	((const #f))))
;      ((if-3 (const #f) (const #f) (const #<void>)))))
;(equal? (rep (define bin
;     (lambda (n s)
;       (if (zero? n) (list s)
;	   (append
;	    (bin (sub1 n) (cons 0 s))
;	    (bin (sub1 n) (cons 1 s))))))
;(define (free-var bin)
;     (lambda-simple
;      (n s)
;      (if-3 (applic (free-var zero?) ((param-var n 0)))
;	   (tc-applic (free-var list) ((param-var s 1)))
;	   (tc-applic
;	    (free-var append)
;	    ((applic
;	      (free-var bin)
;	      ((applic (free-var sub1) ((param-var n 0)))
;	       (applic (free-var cons) ((const 0) (param-var s 1)))))
;	     (applic
;	      (free-var bin)
;	      ((applic (free-var sub1) ((param-var n 0)))
;	       (applic (free-var cons) ((const 1) (param-var s 1))))))))))
;(equal? (rep (define cross-map
;     (lambda (s f)
;       (letrec ((run-h
;		 (lambda (s args)
;		   (if (null? s)
;		       (list (apply f (reverse args)))
;		       (run-v (car s) (cdr s) args))))
;		(run-v
;		 (lambda (n s args)
;		   (if (zero? n)
;		       '()
;		       (append
;			(run-h s (cons (- n 1) args))
;			(run-v (- n 1) s args))))))
;	 (run-h s '()))))
;(define (free-var cross-map)
;     (lambda-simple
;      (s f)
;      (tc-applic
;       (lambda-simple
;	(run-h run-v)
;	(seq ((set (param-var run-h 0)
;		   (applic (free-var cons) ((param-var run-h 0) (const ()))))
;	      (set (param-var run-v 1)
;		   (applic (free-var cons) ((param-var run-v 1) (const ()))))
;	      (applic
;	       (free-var set-car!)
;	       ((param-var run-h 0)
;		(lambda-simple
;		 (s args)
;		 (if-3 (applic (free-var null?) ((param-var s 0)))
;		      (tc-applic
;		       (free-var list)
;		       ((applic
;			 (free-var apply)
;			 ((bound-var f 1 1)
;			  (applic
;			   (free-var reverse)
;			   ((param-var args 1)))))))
;		      (tc-applic
;		       (applic (free-var car) ((bound-var run-v 0 1)))
;		       ((applic (free-var car) ((param-var s 0)))
;			(applic (free-var cdr) ((param-var s 0)))
;			(param-var args 1)))))))
;	      (applic
;	       (free-var set-car!)
;	       ((param-var run-v 1)
;		(lambda-simple
;		 (n s args)
;		 (if-3 (applic (free-var zero?) ((param-var n 0)))
;		      (const ())
;		      (tc-applic
;		       (free-var append)
;		       ((applic
;			 (applic (free-var car) ((bound-var run-h 0 0)))
;			 ((param-var s 1)
;			  (applic
;			   (free-var cons)
;			   ((applic
;			     (free-var -)
;			     ((param-var n 0) (const 1)))
;			    (param-var args 2)))))
;			(applic
;			 (applic (free-var car) ((bound-var run-v 0 1)))
;			 ((applic
;			   (free-var -)
;			   ((param-var n 0) (const 1)))
;			  (param-var s 1)
;			  (param-var args 2)))))))))
;	      (tc-applic
;	       (applic (free-var car) ((param-var run-h 0)))
;	       ((bound-var s 0 0) (const ()))))))
;       ((const #f) (const #f)))))
;(equal? (rep (define show
;     ((lambda (ma)
;	((lambda (ai)
;	   (lambda (board)
;	     ((board (ma ai 'x) (ma ai 'o) (ma ai'_))
;	      (lambda (x y) (lambda (r) `(lambda (x o _) ,r)))
;	      #f)))
;	 (lambda (m1 m2)
;	   (lambda (c)
;	     (lambda (b)
;	       (lambda (a)
;		 (ma m1 (list a b c))))))))
;      (lambda (m r) (lambda (x y) ((x y m) r)))))
;(define (free-var show)
;     (applic
;      (lambda-simple
;       (ma)
;       (tc-applic
;	(lambda-simple
;	 (ai)
;	 (lambda-simple
;	  (board)
;	  (tc-applic
;	   (applic
;	    (param-var board 0)
;	    ((applic (bound-var ma 1 0) ((bound-var ai 0 0) (const x)))
;	     (applic (bound-var ma 1 0) ((bound-var ai 0 0) (const o)))
;	     (applic (bound-var ma 1 0) ((bound-var ai 0 0) (const _)))))
;	   ((lambda-simple
;	     (x y)
;	     (lambda-simple
;	      (r)
;	      (tc-applic
;	       (free-var append)
;	       ((const (lambda))
;		(applic
;		 (free-var append)
;		 ((applic
;		   (free-var list)
;		   ((applic
;		     (free-var append)
;		     ((const (x))
;		      (applic
;		       (free-var append)
;		       ((const (o))
;			(applic
;			 (free-var append)
;			 ((const (_)) (const ())))))))))
;		  (applic
;		   (free-var append)
;		   ((applic (free-var list) ((param-var r 0)))
;		    (const ())))))))))
;	    (const #f)))))
;	((lambda-simple
;	  (m1 m2)
;	  (lambda-simple
;	   (c)
;	   (lambda-simple
;	    (b)
;	    (lambda-simple
;	     (a)
;	     (tc-applic
;	      (bound-var ma 3 0)
;	      ((bound-var m1 2 0)
;	       (applic
;		(free-var list)
;		((param-var a 0) (bound-var b 0 0) (bound-var c 1 0))))))))))))
;      ((lambda-simple
;	(m r)
;	(lambda-simple
;	 (x y)
;	 (tc-applic
;	  (applic (param-var x 0) ((param-var y 1) (bound-var m 0 0)))
;	  ((bound-var r 0 1))))))))
;(equal? (rep (define qsort
;     (lambda (s)
;       (if (null? s) '()
;	   (split (car s) (cdr s)
;		  (lambda (ll gl)
;		    (append (qsort ll)
;			    (list (car s))
;			    (qsort gl)))))))
;(define (free-var qsort)
;     (lambda-simple
;      (s)
;      (if-3 (applic (free-var null?) ((param-var s 0)))
;	   (const ())
;	   (tc-applic
;	    (free-var split)
;	    ((applic (free-var car) ((param-var s 0)))
;	     (applic (free-var cdr) ((param-var s 0)))
;	     (lambda-simple
;	      (ll gl)
;	      (tc-applic
;	       (free-var append)
;	       ((applic (free-var qsort) ((param-var ll 0)))
;		(applic
;		 (free-var list)
;		 ((applic (free-var car) ((bound-var s 0 0)))))
;		(applic (free-var qsort) ((param-var gl 1)))))))))))
;(equal? (rep (define split
;     (lambda (pivot s ret-ll+gl)
;       (if (null? s) (ret-ll+gl '() '())
;	   (split pivot (cdr s)
;		  (lambda (ll gl)
;		    (if (<= (car s) pivot)
;			(ret-ll+gl (cons (car s) ll) gl)
;			(ret-ll+gl ll (cons (car s) gl))))))))
;(define (free-var split)
;     (lambda-simple
;      (pivot s ret-ll+gl)
;      (if-3 (applic (free-var null?) ((param-var s 1)))
;	   (tc-applic (param-var ret-ll+gl 2) ((const ()) (const ())))
;	   (tc-applic
;	    (free-var split)
;	    ((param-var pivot 0)
;	     (applic (free-var cdr) ((param-var s 1)))
;	     (lambda-simple
;	      (ll gl)
;	      (if-3 (applic
;		    (free-var <=)
;		    ((applic (free-var car) ((bound-var s 0 1)))
;		     (bound-var pivot 0 0)))
;		   (tc-applic
;		    (bound-var ret-ll+gl 0 2)
;		    ((applic
;		      (free-var cons)
;		      ((applic (free-var car) ((bound-var s 0 1)))
;		       (param-var ll 0)))
;		     (param-var gl 1)))
;		   (tc-applic
;		    (bound-var ret-ll+gl 0 2)
;		    ((param-var ll 0)
;		     (applic
;		      (free-var cons)
;		      ((applic (free-var car) ((bound-var s 0 1)))
;		       (param-var gl 1))))))))))))
;(equal? (rep (a (lambda (a) (a (lambda (b) (a b (lambda (a) (a b (lambda (c) (a b c)))))))))
;(tc-applic
; (free-var a)
; ((lambda-simple
;   (a)
;   (tc-applic
;    (param-var a 0)
;    ((lambda-simple
;      (b)
;      (tc-applic
;       (bound-var a 0 0)
;       ((param-var b 0)
;	(lambda-simple
;	 (a)
;	 (tc-applic
;	  (param-var a 0)
;	  ((bound-var b 0 0)
;	   (lambda-simple
;	    (c)
;	    (tc-applic
;	     (bound-var a 0 0)
;	     ((bound-var b 1 0) (param-var c 0)))))))))))))))
;(equal? (rep (define list->string
;     (lambda (s)
;       (let* ((n (length s))
;	      (str (make-string n)))
;	 (letrec ((loop
;		   (lambda (s i)
;		     (if (= i n) str
;			 (begin
;			   (string-set! str i (car s))
;			   (loop (cdr s) (+ i 1)))))))
;	   (loop s 0)))))
;(define (free-var list->string)
;     (lambda-simple
;      (s)
;      (tc-applic
;       (lambda-simple
;	(n)
;	(tc-applic
;	 (lambda-simple
;	  (str)
;	  (tc-applic
;	   (lambda-simple
;	    (loop)
;	    (seq ((set (param-var loop 0)
;		       (applic
;			(free-var cons)
;			((param-var loop 0) (const ()))))
;		  (applic
;		   (free-var set-car!)
;		   ((param-var loop 0)
;		    (lambda-simple
;		     (s i)
;		     (if-3 (applic
;			   (free-var =)
;			   ((param-var i 1) (bound-var n 2 0)))
;			  (bound-var str 1 0)
;			  (seq ((applic
;				 (free-var string-set!)
;				 ((bound-var str 1 0)
;				  (param-var i 1)
;				  (applic
;				   (free-var car)
;				   ((param-var s 0)))))
;				(tc-applic
;				 (applic
;				  (free-var car)
;				  ((bound-var loop 0 0)))
;				 ((applic
;				   (free-var cdr)
;				   ((param-var s 0)))
;				  (applic
;				   (free-var +)
;				   ((param-var i 1)
;				    (const 1)))))))))))
;		  (tc-applic
;		   (applic (free-var car) ((param-var loop 0)))
;		   ((bound-var s 2 0) (const 0))))))
;	   ((const #f))))
;	 ((applic (free-var make-string) ((param-var n 0))))))
;       ((applic (free-var length) ((param-var s 0)))))))
;(equal? (rep (define list->vector
;     (lambda (s)
;       (let* ((n (length s))
;	      (v (make-vector n)))
;	 (letrec ((loop
;		   (lambda (s i)
;		     (if (= i n) v
;			 (begin
;			   (vector-set! v i (car s))
;			   (loop (cdr s) (+ i 1)))))))
;	   (loop s 0)))))
;(define (free-var list->vector)
;     (lambda-simple
;      (s)
;      (tc-applic
;       (lambda-simple
;	(n)
;	(tc-applic
;	 (lambda-simple
;	  (v)
;	  (tc-applic
;	   (lambda-simple
;	    (loop)
;	    (seq ((set (param-var loop 0)
;		       (applic
;			(free-var cons)
;			((param-var loop 0) (const ()))))
;		  (applic
;		   (free-var set-car!)
;		   ((param-var loop 0)
;		    (lambda-simple
;		     (s i)
;		     (if-3 (applic
;			   (free-var =)
;			   ((param-var i 1) (bound-var n 2 0)))
;			  (bound-var v 1 0)
;			  (seq ((applic
;				 (free-var vector-set!)
;				 ((bound-var v 1 0)
;				  (param-var i 1)
;				  (applic
;				   (free-var car)
;				   ((param-var s 0)))))
;				(tc-applic
;				 (applic
;				  (free-var car)
;				  ((bound-var loop 0 0)))
;				 ((applic
;				   (free-var cdr)
;				   ((param-var s 0)))
;				  (applic
;				   (free-var +)
;				   ((param-var i 1)
;				    (const 1)))))))))))
;		  (tc-applic
;		   (applic (free-var car) ((param-var loop 0)))
;		   ((bound-var s 2 0) (const 0))))))
;	   ((const #f))))
;	 ((applic (free-var make-vector) ((param-var n 0))))))
;       ((applic (free-var length) ((param-var s 0)))))))
;(equal? (rep (define pred
;     (lambda (n)
;       (lambda (z)
;	 (lambda (w)
;	   (let
;	       ((M (lambda (m)
;		     (lambda (b2)
;		       (lambda (r21)
;			 (lambda (r22)
;			   (lambda (s2)
;			     (lambda (b1)
;			       (lambda (r11)
;				 (lambda (r12)
;				   (lambda (s1)
;				     ((s1
;				       (((b1
;					  (((b2 (quintuple m b2 (r12 w) (r12 w) U01))
;					    (quintuple m b2 (r12 w) (r12 w) U01))
;					   (r12 w)))
;					 (((b2 (quintuple m b2 r11 (r12 z) U11))
;					   (quintuple m b2 r11 (r12 z) U11))
;					  r11))
;					I))
;				      (((b1 (((b2 (quintuple m b2 r11 (r12 z) U11))
;					      (quintuple m b2 r11 (r12 z) U11))
;					     r11))
;					(((b2 (quintuple m b2 (r12 w) (r12 w) U11))
;					  (quintuple m b2 (r12 w) (r12 w) U11))
;					 (r12 w)))
;				       I)))))))))))))
;	     (((n (quintuple M U02 z I U01))
;	       (quintuple M U12 z I U01))
;	      (quintuple M U22 z I U01)))))))
;(define (free-var pred)
;     (lambda-simple
;      (n)
;      (lambda-simple
;       (z)
;       (lambda-simple
;	(w)
;	(tc-applic
;	 (lambda-simple
;	  (M)
;	  (tc-applic
;	   (applic
;	    (applic
;	     (bound-var n 2 0)
;	     ((applic
;	       (free-var quintuple)
;	       ((param-var M 0)
;		(free-var U02)
;		(bound-var z 1 0)
;		(free-var I)
;		(free-var U01)))))
;	    ((applic
;	      (free-var quintuple)
;	      ((param-var M 0)
;	       (free-var U12)
;	       (bound-var z 1 0)
;	       (free-var I)
;	       (free-var U01)))))
;	   ((applic
;	     (free-var quintuple)
;	     ((param-var M 0)
;	      (free-var U22)
;	      (bound-var z 1 0)
;	      (free-var I)
;	      (free-var U01))))))
;	 ((lambda-simple
;	   (m)
;	   (lambda-simple
;	    (b2)
;	    (lambda-simple
;	     (r21)
;	     (lambda-simple
;	      (r22)
;	      (lambda-simple
;	       (s2)
;	       (lambda-simple
;		(b1)
;		(lambda-simple
;		 (r11)
;		 (lambda-simple
;		  (r12)
;		  (lambda-simple
;		   (s1)
;		   (tc-applic
;		    (applic
;		     (param-var s1 0)
;		     ((applic
;		       (applic
;			(applic
;			 (bound-var b1 2 0)
;			 ((applic
;			   (applic
;			    (applic
;			     (bound-var b2 6 0)
;			     ((applic
;			       (free-var quintuple)
;			       ((bound-var m 7 0)
;				(bound-var b2 6 0)
;				(applic
;				 (bound-var r12 0 0)
;				 ((bound-var w 8 0)))
;				(applic
;				 (bound-var r12 0 0)
;				 ((bound-var w 8 0)))
;				(free-var U01)))))
;			    ((applic
;			      (free-var quintuple)
;			      ((bound-var m 7 0)
;			       (bound-var b2 6 0)
;			       (applic
;				(bound-var r12 0 0)
;				((bound-var w 8 0)))
;			       (applic
;				(bound-var r12 0 0)
;				((bound-var w 8 0)))
;			       (free-var U01)))))
;			   ((applic
;			     (bound-var r12 0 0)
;			     ((bound-var w 8 0)))))))
;			((applic
;			  (applic
;			   (applic
;			    (bound-var b2 6 0)
;			    ((applic
;			      (free-var quintuple)
;			      ((bound-var m 7 0)
;			       (bound-var b2 6 0)
;			       (bound-var r11 1 0)
;			       (applic
;				(bound-var r12 0 0)
;				((bound-var z 9 0)))
;			       (free-var U11)))))
;			   ((applic
;			     (free-var quintuple)
;			     ((bound-var m 7 0)
;			      (bound-var b2 6 0)
;			      (bound-var r11 1 0)
;			      (applic
;			       (bound-var r12 0 0)
;			       ((bound-var z 9 0)))
;			      (free-var U11)))))
;			  ((bound-var r11 1 0)))))
;		       ((free-var I)))))
;		    ((applic
;		      (applic
;		       (applic
;			(bound-var b1 2 0)
;			((applic
;			  (applic
;			   (applic
;			    (bound-var b2 6 0)
;			    ((applic
;			      (free-var quintuple)
;			      ((bound-var m 7 0)
;			       (bound-var b2 6 0)
;			       (bound-var r11 1 0)
;			       (applic
;				(bound-var r12 0 0)
;				((bound-var z 9 0)))
;			       (free-var U11)))))
;			   ((applic
;			     (free-var quintuple)
;			     ((bound-var m 7 0)
;			      (bound-var b2 6 0)
;			      (bound-var r11 1 0)
;			      (applic
;			       (bound-var r12 0 0)
;			       ((bound-var z 9 0)))
;			      (free-var U11)))))
;			  ((bound-var r11 1 0)))))
;		       ((applic
;			 (applic
;			  (applic
;			   (bound-var b2 6 0)
;			   ((applic
;			     (free-var quintuple)
;			     ((bound-var m 7 0)
;			      (bound-var b2 6 0)
;			      (applic
;			       (bound-var r12 0 0)
;			       ((bound-var w 8 0)))
;			      (applic
;			       (bound-var r12 0 0)
;			       ((bound-var w 8 0)))
;			      (free-var U11)))))
;			  ((applic
;			    (free-var quintuple)
;			    ((bound-var m 7 0)
;			     (bound-var b2 6 0)
;			     (applic
;			      (bound-var r12 0 0)
;			      ((bound-var w 8 0)))
;			     (applic
;			      (bound-var r12 0 0)
;			      ((bound-var w 8 0)))
;			     (free-var U11)))))
;			 ((applic
;			   (bound-var r12 0 0)
;			   ((bound-var w 8 0)))))))
;		      ((free-var I))))))))))))))))))))
;(equal? (rep (define Yn
;     (lambda fs
;       (let ((ms (map
;		     (lambda (fi)
;		       (lambda ms
;			 (apply fi (map (lambda (mi)
;					  (lambda args
;					    (apply (apply mi ms) args))) ms))))
;		   fs)))
;	 (apply (car ms) ms))))
;(define (free-var Yn)
;     (lambda-variadic
;      fs
;      (tc-applic
;       (lambda-simple
;	(ms)
;	(tc-applic
;	 (free-var apply)
;	 ((applic (free-var car) ((param-var ms 0))) (param-var ms 0))))
;       ((applic
;	 (free-var map)
;	 ((lambda-simple
;	   (fi)
;	   (lambda-variadic
;	    ms
;	    (tc-applic
;	     (free-var apply)
;	     ((bound-var fi 0 0)
;	      (applic
;	       (free-var map)
;	       ((lambda-simple
;		 (mi)
;		 (lambda-variadic
;		  args
;		  (tc-applic
;		   (free-var apply)
;		   ((applic
;		     (free-var apply)
;		     ((bound-var mi 0 0) (bound-var ms 1 0)))
;		    (param-var args 0)))))
;		(param-var ms 0)))))))
;	  (param-var fs 0)))))))
)